#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>

#define PORT 12345
#define MAX_BUFFER_SIZE 1024

int main() {
    int sockfd, new_fd;
    struct sockaddr_in server_addr, client_addr;
    socklen_t client_len;

    // Step 2: Create socket
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        perror("Socket creation failed");
        exit(EXIT_FAILURE);
    }

    // Step 3: Configure address structure
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(PORT);
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);

    // Step 4: Bind
    if (bind(sockfd, (struct sockaddr *) &server_addr, sizeof(server_addr)) == -1) {
        perror("Bind failed");
        close(sockfd);
        exit(EXIT_FAILURE);
    }

    // Step 5: Listen
    if (listen(sockfd, SOMAXCONN) == -1) {
        perror("Listen failed");
        close(sockfd);
        exit(EXIT_FAILURE);
    }
    printf("Server is listening on port %d...\n", PORT);

    // Accept connections and handle data
    while (1) {
        client_len = sizeof(client_addr);
        if ((new_fd = accept(sockfd, (struct sockaddr *) &client_addr, &client_len)) == -1) {
            perror("Accept failed");
            continue;
        }

        char client_ip[INET_ADDRSTRLEN];
        inet_ntop(AF_INET, &client_addr.sin_addr, client_ip, sizeof(client_ip));

        printf("Connection accepted from %s:%d\n", client_ip, ntohs(client_addr.sin_port));

        // Read and echo data back to the client
        char buffer[MAX_BUFFER_SIZE];
        ssize_t bytes_read;

        while ((bytes_read = recv(new_fd, buffer, MAX_BUFFER_SIZE - 1, 0)) > 0) {
            buffer[bytes_read] = '\0'; // Null-terminate the received data

            printf("Received message: %s\n", buffer);
        }

        if (bytes_read == 0) {
            printf("Client disconnected\n");
        } else if (bytes_read == -1) {
            perror("Recv failed");
        }

        // Close the connection
        close(new_fd);
        break;
    }

    // Close the server socket (unreachable in this infinite loop setup)
    close(sockfd);

    return 0;
}
